home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
asmbler.arc
/
IBMSPEC.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-11-19
|
14KB
|
383 lines
; [23-Feb-84]
; Added GETATTR routine and added attribute value to arglist of writer
; to support inverse video, blinking, etc.
; <BEEBE.IBM-PC>IBMSPEC.ASM.22, 20-Feb-84 13:52:00, Edit by BEEBE
; [20-Feb-84]
; alphabetized routines (except for SCREENHEIGHT and SCREENHEIGHT because
; of stupid assembler bug), prettyprinted code, inserted symbolic DOS/BIOS
; interrupts and function codes, added SCREENHEIGHT and CURRXY routines,
; made SCREENHEIGHT and SCREENWIDTH support standard IBM monitors as well
; as Quadram Quadscreen
USE_SCROLL EQU 0
TRY_INVERSE EQU 0
DEBUG EQU 1
assume cs:ibmspec
public bell, currxy, eeol, eeos, getattr, gotoxy, screenheight, screenwidth
public writer
include ascii.inc
include dos.inc
ibmspec segment para public 'code'
enter macro
push bp ; save old frame pointer
mov bp,sp ; make new frame pointer
add bp,6 ; pointing to args on stack
endm
exit macro
pop bp ; restore old frame pointer
endm
enterds macro
push bp ; save old frame pointer and data
push ds ; segment register
mov bp,sp ; and make new frame pointer pointing to
add bp,8 ; args on stack
endm
exitds macro
pop ds ; restore data segment register and old
pop bp ; frame pointer
endm
wonb equ 7 ; video mode for white char on black background
;=======================================================================
; Function Screenheight : word { return screen height in ax }
assume cs:ibmspec
screenheight proc far
mov ah,$VIDEO_GETVIDEOSTATE
int $VIDEO ; current mode to al
xor bx,bx ; clear bx
mov ah,$QS_DESCRIBEMODE
int $VIDEO ; get Quadscreen status (if any)
test bx,bx ; bx = 0 still?
jz stdht ; yes, standard IBM mode
mov al,bh ; Quadscreen height
xor ah,ah ; clear top half of ax
ret
stdht:
mov ax,25 ; IBM modes 0..7 are all 25 lines
ret
screenheight endp
;=======================================================================
; Function Screenwidth : word { return screen width in ax }
assume cs:ibmspec,ds:ibmspec
screenwidth proc far
mov ah,$VIDEO_GETVIDEOSTATE
int $VIDEO ; current mode to al
xor bx,bx ; clear bx
mov ah,$QS_DESCRIBEMODE
int $VIDEO ; get Quadscreen status (if any)
test bx,bx ; bx = 0 still?
jz stdwd ; yes, standard IBM mode
mov al,bl ; Quadscreen width
xor ah,ah ; clear top half of ax
ret ; return to caller
stdwd:
mov bl,al ; mode
and bx,7 ; clear all but 3 lower bits
sal bl,1 ; 2*mode for table word index
push ds ; save ds
push cs
pop ds ; make ds = cs
mov ax,wtable[bx] ; screen width according to mode
pop ds ; restore ds
ret ; return to caller
wtable: dw 40 ; mode = 0
dw 40 ; 1
dw 80 ; 2
dw 80 ; 3
dw 80 ; 4
dw 80 ; 5
dw 80 ; 6
dw 80 ; 7
screenwidth endp
;=======================================================================
; Procedure Bell { ring the bell }
assume cs:ibmspec
kb_ctl equ 61h ; speaker I/O address
bell proc far
in al,kb_ctl
push ax ; save current port contents
mov bx,0c0h ; outer loop delay count
b65:
and al,0fch
out kb_ctl,al
mov cx,48h ; delay loop count
b66:
loop b66 ; do the delay
or al,2
out kb_ctl,al
mov cx,48h ; delay loop count
b67:
loop b67 ; do the delay
dec bx ; outer loop done?
jnz b65 ; loop back if not
pop ax ; recall original port contents
out kb_ctl,al ; and restore them
ret ; return to caller
bell endp
;=======================================================================
; Procedure Currxy (column,row : word); { return current cursor position }
assume cs:ibmspec
currxy proc far
enter
mov ah,$VIDEO_GETVIDEOSTATE
int $VIDEO ; get current mode, width, page
mov ah,$VIDEO_GETCURSORPOSITION
int $VIDEO ; get (row,column) in (dh,dl)
xor ah,ah ; clear top half of ax
mov al,dl ; column
mov [bp+2],ax ; store column
mov al,dh ; row
mov [bp],ax ; store row
exit
ret 4 ; return discarding stack arguments
currxy endp
;=======================================================================
; Procedure Eeol { erase from cursor to end of line }
assume cs:ibmspec
db "<<EEOL>>"
eeol proc far
call screenwidth
mov si,ax ; save screen width
mov ah,$VIDEO_GETCURSORPOSITION
int $VIDEO ; get cursor (row,column) in (dh,dl)
xor dh,dh ; clear row
sub si,dx ; length of remainder of screen line
jle e1 ; exit if nothing to clear
mov cx,si ; count
mov al,' ' ; blank for clearing
mov bl,wonb ; video attribute
mov ah,$VIDEO_SETATTRCHAR
int $VIDEO ; erase the rest of the line
e1:
ret ; return to caller
eeol endp
;=======================================================================
; Procedure Eeos { erase from cursor to end of screen }
assume cs:ibmspec
db "<<EEOS>>"
eeos proc far
enter
call screenwidth
mov si,ax ; save screen width
call screenheight
mov di,ax ; save screen height
mov ah,$VIDEO_GETVIDEOSTATE
int $VIDEO ; get current mode, width, and page (in bh)
mov ah,$VIDEO_GETCURSORPOSITION
int $VIDEO ; get (row,column) in (dh,dl)
IF USE_SCROLL
test dx,dx ; at (0,0)?
jnz sloweeos ; no
mov ax,di ; height
dec al ; height-1
mov dh,al ; height-1
mov ax,si ; width
dec al ; width-1
mov dl,al ; (height-1,width-1) in (dh,dl) = lower right
xor cx,cx ; set upper left corner of scroll = (0,0)
xor al,al ; al = 0 means blank entire page
mov ah,$VIDEO_SCROLLUP
int $VIDEO ; do fast screen clear
jmp eeosdone
ENDIF
sloweeos: ; slow erase of partial screen
mov ax,di ; screen height
mov cx,si ; screen width
mul cl ; (height)*(width) = screen size in cx
mov di,ax ; save screen size
mov ax,si ; screen width
mul dh ; (row)*(width) = count from bol to eos
xor dh,dh ; column in dx
sub di,ax ; (screen chars) - (count from bol to eos)
sub di,dx ; - column =
mov cx,di ; count of chars to blank
mov al,' '
mov bl,wonb ; video mode
mov ah,$VIDEO_SETATTRCHAR
int $VIDEO ; blank rest of screen
eeosdone:
exit
ret
eeos endp
;=======================================================================
; Function Getattr : word { Return video attr of character at cursor }
;
assume cs:ibmspec
db "<<GETATTR>>"
getattr proc far
mov ah,$VIDEO_GETVIDEOSTATE
int $VIDEO ; get current mode, width, and page
mov ah,$VIDEO_GETATTRCHAR
int $VIDEO
mov al,ah ; attribute in al
xor ah,ah ; clear top of ax (function result)
ret ; return to caller
getattr endp
;=======================================================================
; Procedure Gotoxy (column,row : word) { Move cursor to (column,row) }
assume cs:ibmspec
db "<<GOTOXY>>"
gotoxy proc far
enter
mov ah,$VIDEO_GETVIDEOSTATE
int $VIDEO ; get current mode, width, and page
mov dl,[bp+2] ; column
mov dh,[bp] ; row
xor bh,bh ; current page = 0
mov ah,$VIDEO_SETCURSORPOSITION
int $VIDEO
exit
ret 4 ; return discarding stack arguments
gotoxy endp
;=======================================================================
; Procedure Writer (attr: word; thestr: adsmem; count: integer);
; { Write 'count' characters of 'thestr' at the current cursor position
; using video attribute attr (e.g. obtained by Getattr).
; Characters beyond the end-of-screen-line are not displayed. }
;
; Stack looks like
; 0 - count
; 2 - address of thestr
; 4 - segment of thestr
; 6 - attr
assume cs:ibmspec
;
; IBM monitor attribute byte bit assignments
; -------------------------------------
; | blink | R | G | B | I | R | G | B |
; -------------------------------------
; ----- -----
; back fore
;
blink equ 80h
intensity equ 08h
forergb equ 70h
backrgb equ 07h
db "<<WRITER>>"
writer proc far
enterds
mov di,[bp] ; grab the count
test di,di ; count > 0 ?
jle writerdone ; exit if nothing to write
mov si,[bp+2] ; grab the address of the characters to write
mov ds,[bp+4] ; grab the segment of thestr
call screenwidth
push ax ; save screen width
mov ah,$VIDEO_GETCURSORPOSITION
int $VIDEO
pop ax ; recall screen width
dec ax ; al = width of screen, dl = cursor column
mov bl,al ; save maximum displayable column in bl
sub al,dl ; maximum number of chars to write
jle writerdone ; exit if nothing to write
xor ah,ah ; clear top of ax
cmp di,ax ; user-specified count > remaining line length?
jle writ2 ; no
mov di,ax ; yes, truncate the line
writ2:
cld ; clear direction flag to increment si
mov ah,$VIDEO_GETVIDEOSTATE
int $VIDEO ; get current page in (bh)
mov ah,$VIDEO_GETCURSORPOSITION
int $VIDEO ; get (row,column) in (dh,dl)
push dx ; save it - later accessed by [bp-10]
writlp:
lodsb ; get next byte into al and increment si
mov cx,1 ; repeat count = 1
cmp al,.HT ; tab?
jne writ3 ; no
mov cl,[bp-10] ; yes, get current cursor column (0,1,2,...)
and cl,7 ; cl MOD 8
neg cl ; -(cl MOD 8)
add cl,8 ; 8 - (cl MOD 8) = columns of blank fill
mov al,' ' ; change tab to blank
writ3:
mov dl,[bp-10] ; current column
add dl,cl ; new column
cmp bl,dl ; maximum column < new current column?
jl writerdone ; yes, no more room in current line
mov [bp-10],dl ; update cursor column
if DEBUG
mov bl,7
else
mov bl,[bp+6] ; get attribute byte
endif
if TRY_INVERSE
;
; display the character in the inverse of the current mode
; [experiment]
;
mov ah,$VIDEO_GETATTRCHAR
int $VIDEO ; get (attribute,char) in (ah,al) for page (bh)
push cx ; save count
mov bl,ah ; mode byte
and bl,blink+intensity ; keep blink and intensity bits
and ah,NOT (blink OR intensity) ; remove blink and intensity
mov ch,ah
mov cl,4 ; shift count
shr ch,cl ; move foreground into background,
shl ah,cl ; background into foreground,
or ah,ch ; merge them,
or ah,bl ; restore blink and intensity for new mode,
pop cx ; restore count
mov bl,ah ; and setup new mode.
endif
writ4:
mov ah,$VIDEO_SETATTRCHAR
int $VIDEO ; write char and attribute
mov dl,[bp-10] ; get current cursor column
mov ah,$VIDEO_SETCURSORPOSITION
int $VIDEO ; move cursor
dec di ; are we done?
jnz writlp ; loop for more if not
pop dx ; restore saved dx
writerdone:
exitds ; restore stack at entry
ret 8 ; return discarding arguments on stack
writer endp
ibmspec ends
end